package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.ResultConstants;
import com.ruoyi.common.enums.TradeType;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.support.Convert;
import com.ruoyi.common.utils.BigDecimalUtil;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.system.domain.WdyHuobiTrade;
import com.ruoyi.system.domain.WdyUser;
import com.ruoyi.system.mapper.WdyHuobiTradeMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.IWdyHuobiTradeService;
import com.ruoyi.system.service.IWdyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 火币委托交易 服务层实现
 * 
 * @author ruoyi
 * @date 2020-03-08
 */
@Service
public class WdyHuobiTradeServiceImpl extends ServiceImpl<WdyHuobiTradeMapper, WdyHuobiTrade> implements IWdyHuobiTradeService
{
	@Autowired
	private IWdyUserService wdyUserService;

	@Autowired
	private ISysConfigService sysConfigService;
	/**
     * 查询火币委托交易信息
     * 
     * @param id 火币委托交易ID
     * @return 火币委托交易信息
     */
    @Override
	public WdyHuobiTrade selectWdyHuobiTradeById(Long id)
	{
	    return baseMapper.selectWdyHuobiTradeById(id);
	}
	
	/**
     * 查询火币委托交易列表
     * 
     * @param wdyHuobiTrade 火币委托交易信息
     * @return 火币委托交易集合
     */
	@Override
	public List<WdyHuobiTrade> selectWdyHuobiTradeList(WdyHuobiTrade wdyHuobiTrade)
	{
	    return baseMapper.selectWdyHuobiTradeList(wdyHuobiTrade);
	}
	
    /**
     * 新增火币委托交易
     * 
     * @param wdyHuobiTrade 火币委托交易信息
     * @return 结果
     */
	@Override
	public int insertWdyHuobiTrade(WdyHuobiTrade wdyHuobiTrade)
	{
	    return baseMapper.insertWdyHuobiTrade(wdyHuobiTrade);
	}
	
	/**
     * 修改火币委托交易
     * 
     * @param wdyHuobiTrade 火币委托交易信息
     * @return 结果
     */
	@Override
	public int updateWdyHuobiTrade(WdyHuobiTrade wdyHuobiTrade)
	{
	    return baseMapper.updateWdyHuobiTrade(wdyHuobiTrade);
	}

	/**
     * 删除火币委托交易对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
	@Override
	public int deleteWdyHuobiTradeByIds(String ids)
	{
		return baseMapper.deleteWdyHuobiTradeByIds(Convert.toStrArray(ids));
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void trade(WdyHuobiTrade trade) {
		Integer tradeType = trade.getTradeType();
		if(tradeType == null) {
			throw new BusinessException(ResultConstants.FI1000, "tradeType " + MessageUtils.message("not.null"));
		}
		if(tradeType.compareTo(TradeType.BUY.getCode()) != 0
				&& tradeType.compareTo(TradeType.SELL.getCode()) != 0) {
			throw new BusinessException(ResultConstants.FI1000, "tradeType " + MessageUtils.message("param.error"));
		}

		if(trade.getTradePrice() == null) {
			throw new BusinessException(ResultConstants.FI1000, "tradePrice " + MessageUtils.message("not.null"));
		}
		BigDecimal tradePrice = BigDecimalUtil.getP2BigDecimal(trade.getTradePrice());
		trade.setTradePrice(tradePrice);
		if(tradePrice.compareTo(BigDecimal.ZERO) <= 0) {
			throw new BusinessException(ResultConstants.FI1000, "tradePrice" + MessageUtils.message("param.error"));
		}

		if(trade.getTradeAmount() == null) {
			throw new BusinessException(ResultConstants.FI1000, "tradeAmount" + MessageUtils.message("not.null"));
		}
		BigDecimal tradeAmount = BigDecimalUtil.getPDecimal(trade.getTradeAmount(), 4);
		trade.setTradeAmount(tradeAmount);
		if(tradeAmount.compareTo(BigDecimal.ZERO) <= 0) {
			throw new BusinessException(ResultConstants.FI1000, "tradeAmount" + MessageUtils.message("param.error"));
		}

		QueryWrapper<WdyUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("user_id", trade.getUserId());
		WdyUser user = wdyUserService.getOne(queryWrapper);

		if(tradeType == TradeType.BUY.getCode()) {
			BigDecimal cnn = BigDecimalUtil.getP2BigDecimal(trade.getTradePrice().multiply(trade.getTradeAmount()));
			if(cnn.compareTo(user.getCnnAmount()) > 0) {
				throw new BusinessException(ResultConstants.EX9110, "CNN余额不足");
			}
			WdyUser wdyUser = new WdyUser();
			wdyUser.setCnnAmount(BigDecimalUtil.getP2BigDecimal(user.getCnnAmount().subtract(cnn)));
			wdyUser.setVersion(user.getVersion());
			if(!wdyUserService.update(wdyUser, queryWrapper)) {
				throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
			}

		} else if(tradeType == TradeType.SELL.getCode()) {
			if(trade.getTradeAmount().compareTo(user.getEthAmount()) > 0) {
				throw new BusinessException(ResultConstants.EX9110, "ETH数量不足");
			}
			WdyUser wdyUser = new WdyUser();
			wdyUser.setEthAmount(user.getEthAmount().subtract(trade.getTradeAmount()));
			wdyUser.setVersion(user.getVersion());
			if(!wdyUserService.update(wdyUser, queryWrapper)) {
				throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
			}
		}
		this.save(trade);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void cancel(Long tradeId, String userId) {
		WdyHuobiTrade trade = this.getById(tradeId);
		if(trade == null || trade.getTradeState() != WdyHuobiTrade.STATE_TRADE
				|| !userId.equals(trade.getUserId())) {
			throw new BusinessException(ResultConstants.FI1000, "委托单不存在或已成交");
		}
		QueryWrapper<WdyUser> userQuery = new QueryWrapper<>();
		userQuery.eq("user_id", trade.getUserId());
		WdyUser user = wdyUserService.getOne(userQuery);
		if(trade.getTradeType() == TradeType.BUY.getCode()) {
			BigDecimal cnn = BigDecimalUtil.getP2BigDecimal(trade.getTradePrice().multiply(trade.getTradeAmount()));
			WdyUser updateUser = new WdyUser();
			updateUser.setId(user.getId());
			updateUser.setCnnAmount(user.getCnnAmount().add(cnn));
			updateUser.setVersion(user.getVersion());
			if(!wdyUserService.updateById(updateUser)) {
				throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
			}
		} else if(trade.getTradeType() == TradeType.SELL.getCode()) {
			WdyUser updateUser = new WdyUser();
			updateUser.setId(user.getId());
			updateUser.setEthAmount(user.getEthAmount().add(trade.getTradeAmount()));
			updateUser.setVersion(user.getVersion());
			if(!wdyUserService.updateById(updateUser)) {
				throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
			}
		}

		UpdateWrapper<WdyHuobiTrade> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("id", tradeId);
		updateWrapper.eq("trade_state", WdyHuobiTrade.STATE_TRADE);
		updateWrapper.set("trade_state", WdyHuobiTrade.STATE_CANCEL);
		updateWrapper.set("finish_time", new Date());
		if(!this.update(updateWrapper)) {
			throw new BusinessException(ResultConstants.EX9999, "系统繁忙，请稍后重试");
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void deal(WdyHuobiTrade trade) {
		BigDecimal ethCommissionRate = new BigDecimal(sysConfigService.selectConfigByKey("eth_trade_commission_rate"));

		QueryWrapper<WdyUser> userQuery = new QueryWrapper<>();
		userQuery.eq("user_id", trade.getUserId());
		WdyUser user = wdyUserService.getOne(userQuery);
		if(trade.getTradeType() == TradeType.BUY.getCode()) {
			BigDecimal eth = trade.getTradeAmount();
			BigDecimal ethCommission = BigDecimalUtil.getPDecimal(eth.multiply(ethCommissionRate), 4);
			BigDecimal actualEth = eth.subtract(ethCommission);
			WdyUser updateUser = new WdyUser();
			updateUser.setId(user.getId());
			updateUser.setEthAmount(user.getEthAmount().add(actualEth));
			updateUser.setVersion(user.getVersion());
			if(!wdyUserService.updateById(updateUser)) {
				throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
			}
		} else if(trade.getTradeType() == TradeType.SELL.getCode()) {
			BigDecimal cnn = BigDecimalUtil.getP2BigDecimal(trade.getTradePrice().multiply(trade.getTradeAmount()));
			BigDecimal cnnCommission = BigDecimalUtil.getP2BigDecimal(cnn.multiply(ethCommissionRate));
			BigDecimal actualCnn = cnn.subtract(cnnCommission);
			WdyUser updateUser = new WdyUser();
			updateUser.setId(user.getId());
			updateUser.setCnnWithdrawAmount(user.getCnnWithdrawAmount().add(actualCnn));
			updateUser.setVersion(user.getVersion());
			if(!wdyUserService.updateById(updateUser)) {
				throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
			}
		}
		UpdateWrapper<WdyHuobiTrade> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("id", trade.getId());
		updateWrapper.eq("trade_state", WdyHuobiTrade.STATE_TRADE);
		updateWrapper.set("deal_price", trade.getTradePrice());
		updateWrapper.set("deal_total_price", BigDecimalUtil.multiply(trade.getTradePrice(), trade.getTradeAmount()));
		updateWrapper.set("trade_state", WdyHuobiTrade.STATE_FINISH);
		updateWrapper.set("finish_time", new Date());
		if(!this.update(updateWrapper)) {
			throw new BusinessException(ResultConstants.EX9999, "系统繁忙，请稍后重试");
		}
	}
}
